package com.team9.fitness.service;

import com.team9.fitness.dto.FitnessRequest;
import com.team9.fitness.dto.FitnessResponse;
import com.zrdds.infrastructure.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zrdds.simpleinterface.DDSIF;
import com.zrdds.domain.DomainParticipant;
import com.zrdds.domain.DomainParticipantFactory;
import com.zrdds.publication.DataWriter;
import com.zrdds.subscription.DataReader;
import com.zrdds.subscription.SimpleDataReaderListener;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.io.File;

import static com.zrdds.infrastructure.ReturnCode_t.RETCODE_OK;

/**
 * ZRDDS发送服务
 * 负责将请求数据发送给fitness-get模块
 */
@Slf4j
@Service
public class ZRDDSSendService {

    @Value("${zrdds.domain-id}")
    private int domainId;

    @Value("${zrdds.participant-id}")
    private int participantId;

    @Value("${zrdds.qos-profile}")
    private String qosProfile;

    @Value("${zrdds.send.topic-name}")
    private String sendTopicName;

    @Value("${zrdds.receive.topic-name}")
    private String receiveTopicName;

    // 存储等待响应的请求
    private final Map<String, CompletableFuture<FitnessResponse>> pendingRequests = new ConcurrentHashMap<>();

    @Autowired
    private ObjectMapper objectMapper;

    private DomainParticipant participant;
    private DataWriter requestWriter;
    private DataReader responseReader;

    /**
     * 初始化ZRDDS
     */
    public void initialize() {
        try {
            // 使用绝对路径加载ZRDDS库
            String projectRoot = System.getProperty("user.dir");
            String dllPath = projectRoot + File.separator + "lib" + File.separator + "ZRDDS_JAVA.dll";
            
            // 检查DLL文件是否存在
            File dllFile = new File(dllPath);
            if (!dllFile.exists()) {
                throw new RuntimeException("ZRDDS_JAVA.dll文件不存在: " + dllPath);
            }
            
            // 设置库路径到系统属性，确保ZRDDS中间件能找到库
            String libPath = projectRoot + File.separator + "lib";
            String currentLibraryPath = System.getProperty("java.library.path");
            if (currentLibraryPath == null || !currentLibraryPath.contains(libPath)) {
                String newLibraryPath = currentLibraryPath == null ? libPath : currentLibraryPath + File.pathSeparator + libPath;
                System.setProperty("java.library.path", newLibraryPath);
                
                // 重新加载库路径
                try {
                    java.lang.reflect.Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
                    fieldSysPath.setAccessible(true);
                    fieldSysPath.set(null, null);
                    log.info("已重新加载库路径: {}", newLibraryPath);
                } catch (Exception e) {
                    log.warn("无法重新加载库路径: {}", e.getMessage());
                }
            }
            
            // 使用绝对路径加载库
            System.load(dllPath);
            log.info("成功加载ZRDDS库: {}", dllPath);

            // 初始化ZRDDS中间件 - 使用默认配置
            DomainParticipantFactory factory = DDSIF.init("ZRDDS_QOS_PROFILES.xml", "default");
            if (factory == null) {
                throw new RuntimeException("ZRDDS中间件初始化失败");
            }

            // 创建域参与者 - 使用配置文件中的QoS配置
            participant = DDSIF.create_dp(domainId, qosProfile);
            if (participant == null) {
                throw new RuntimeException("创建域参与者失败");
            }

            // 创建发布主题 - 使用配置文件中的QoS配置
            requestWriter = DDSIF.pub_topic(participant, sendTopicName,
                    BytesTypeSupport.get_instance(), qosProfile, null);
            if (requestWriter == null) {
                throw new RuntimeException("创建发布主题失败");
            }

            // 创建订阅主题 - 使用配置文件中的QoS配置
            responseReader = DDSIF.sub_topic(participant, receiveTopicName,
                    BytesTypeSupport.get_instance(), qosProfile, new ResponseListener());
            if (responseReader == null) {
                throw new RuntimeException("创建订阅主题失败");
            }

            log.info("ZRDDS发送服务初始化成功 - 使用QoS配置: {}", qosProfile);

        } catch (Exception e) {
            log.error("ZRDDS发送服务初始化失败", e);
            throw new RuntimeException("ZRDDS初始化失败", e);
        }
    }

    /**
     * 发送请求并等待响应
     */
    public CompletableFuture<FitnessResponse> sendRequest(FitnessRequest request) {
        try {
            // 创建等待响应的Future
            CompletableFuture<FitnessResponse> future = new CompletableFuture<>();
            pendingRequests.put(request.getRequestId(), future);

            // 将请求转换为字节数据
            byte[] requestData = convertRequestToBytes(request);

            // 使用DDSIF.BytesWrite发送数据
            ReturnCode_t result = DDSIF.BytesWrite(domainId, sendTopicName, requestData, requestData.length);
            if (result != RETCODE_OK) {
                throw new RuntimeException("发送请求失败，返回码: " + result);
            }

            log.info("发送请求: {}", request.getRequestId());

            // 设置超时
            future.orTimeout(30, TimeUnit.SECONDS)
                    .whenComplete((response, throwable) -> {
                        if (throwable != null) {
                            log.error("请求超时或失败: {}", request.getRequestId(), throwable);
                            pendingRequests.remove(request.getRequestId());
                        }
                    });

            return future;

        } catch (Exception e) {
            log.error("发送请求失败", e);
            pendingRequests.remove(request.getRequestId());
            throw new RuntimeException("发送请求失败", e);
        }
    }

    /**
     * 响应监听器
     */
    private class ResponseListener extends SimpleDataReaderListener<Bytes, BytesSeq, BytesDataReader> {

        @Override
        public void on_process_sample(DataReader dataReader, Bytes bytes, SampleInfo sampleInfo) {
            try {
                // 将字节数据转换为FitnessResponse对象
                FitnessResponse response = convertBytesToResponse(bytes);
                if (response != null) {
                    String requestId = response.getRequestId();

                    // 添加null检查，避免NullPointerException
                    if (requestId == null || requestId.trim().isEmpty()) {
                        log.error("收到无效响应：requestId为null或空");
                        return;
                    }

                    CompletableFuture<FitnessResponse> future = pendingRequests.get(requestId);

                    if (future != null) {
                        // 检查future是否已经完成，避免重复处理
                        if (!future.isDone()) {
                            future.complete(response);
                            log.info("收到响应: {}", requestId);
                            // 处理完成后移除
                            pendingRequests.remove(requestId);
                        } else {
                            log.debug("响应已处理过，忽略重复响应: {}", requestId);
                        }
                    } else {
                        log.warn("收到未知响应: {}", requestId);
                    }
                }
            } catch (Exception e) {
                log.error("处理响应失败", e);
            }
        }

        @Override
        public void on_data_arrived(DataReader dataReader, Object data, SampleInfo sampleInfo) {
            // 这个方法在SimpleDataReaderListener中是必须实现的，但不会被调用
        }
    }

    /**
     * 将FitnessRequest转换为字节数组
     */
    private byte[] convertRequestToBytes(FitnessRequest request) {
        try {
            String json = objectMapper.writeValueAsString(request);
            return json.getBytes("UTF-8");
        } catch (Exception e) {
            log.error("序列化请求失败", e);
            throw new RuntimeException("序列化失败", e);
        }
    }

    /**
     * 将Bytes对象转换为FitnessResponse
     */
    private FitnessResponse convertBytesToResponse(Bytes bytes) {
        try {
            byte[] data = bytes.value.get_contiguous_buffer();
            int length = bytes.value.length();
            String json = new String(data, 0, length, "UTF-8");
            return objectMapper.readValue(json, FitnessResponse.class);
        } catch (Exception e) {
            log.error("反序列化响应失败", e);
            return null;
        }
    }

    /**
     * 关闭ZRDDS
     */
    public void shutdown() {
        try {
            if (requestWriter != null)
                DDSIF.unpub_topic(requestWriter);
            if (responseReader != null)
                DDSIF.unsub_topic(responseReader);
            if (participant != null) {
                // 使用DomainParticipantFactory的finalize_instance方法
                DomainParticipantFactory.finalize_instance();
            }

            log.info("ZRDDS发送服务已关闭");
        } catch (Exception e) {
            log.error("关闭ZRDDS发送服务失败", e);
        }
    }

    /**
     * 发送用户登录请求
     */
    public CompletableFuture<FitnessResponse> sendUserLoginRequest(String username, String password) {
        try {
            // 创建FitnessRequest对象
            FitnessRequest request = new FitnessRequest();
            request.setRequestId(java.util.UUID.randomUUID().toString());
            request.setRequestType("USER_LOGIN");
            request.setMethod("POST");
            request.setPath("/api/user/signIn");
            request.setUserId(null); // 登录时还没有用户ID

            // 设置请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("username", username);
            requestBody.put("password", password);
            request.setBody(requestBody);

            return sendRequest(request);

        } catch (Exception e) {
            log.error("创建用户登录请求失败", e);
            CompletableFuture<FitnessResponse> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }

    /**
     * 发送用户注册请求
     */
    public CompletableFuture<FitnessResponse> sendUserRegisterRequest(String username, String password,
            String confirmPassword) {
        try {
            // 创建FitnessRequest对象
            FitnessRequest request = new FitnessRequest();
            request.setRequestId(java.util.UUID.randomUUID().toString());
            request.setRequestType("USER_REGISTER");
            request.setMethod("POST");
            request.setPath("/api/user/signUp");
            request.setUserId(null); // 注册时还没有用户ID

            // 设置请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("username", username);
            requestBody.put("password", password);
            requestBody.put("confirmPassword", confirmPassword);
            request.setBody(requestBody);

            return sendRequest(request);

        } catch (Exception e) {
            log.error("创建用户注册请求失败", e);
            CompletableFuture<FitnessResponse> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }

    /**
     * 发送通用业务请求
     */
    public CompletableFuture<FitnessResponse> sendBusinessRequest(String requestType, String method, String path,
            String userId, Map<String, Object> requestBody) {
        try {
            // 创建FitnessRequest对象
            FitnessRequest request = new FitnessRequest();
            request.setRequestId(java.util.UUID.randomUUID().toString());
            request.setRequestType(requestType);
            request.setMethod(method);
            request.setPath(path);
            request.setUserId(userId);
            request.setBody(requestBody);

            return sendRequest(request);

        } catch (Exception e) {
            log.error("创建业务请求失败: type={}, method={}, path={}", requestType, method, path, e);
            CompletableFuture<FitnessResponse> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }
}
